package xyz.bali16.application.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import xyz.bali16.application.config.prop.AuthProp;
import xyz.bali16.application.core.utils.AuthUtils;
import xyz.bali16.application.entity.Menu;
import xyz.bali16.application.mapper.MenuMapper;
import xyz.bali16.application.model.menu.MenuAddParam;
import xyz.bali16.application.model.menu.MenuQueryParam;
import xyz.bali16.application.model.menu.MenuUpdatedParam;
import xyz.bali16.application.service.MenuService;

import com.gitee.starblues.integration.AutoIntegrationConfiguration;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xyz.bali16.application.service.RoleMenuService;

import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    private static final Pattern SLASH_PATTERN = Pattern.compile("/");
    @Autowired
    AuthProp authProp;
    private final RoleMenuService roleMenuService;
    private final AutoIntegrationConfiguration integrationConfiguration;

    private final MenuMapper menuMapper;

    /**
     * 插件组件名称
     */
    private final static String PLUGIN_COMPONENT = "PluginExtensionWeb";

    /**
     * 父目录组件名称
     */
    private final static String PARENT_COMPONENT = "RouteView";


    @Transactional
    @Override
    public void updateStatus(Long menuId, int status) {
        Set<Long> menuIds = Sets.newHashSet(menuId);
        //TODO 处理子结点状态

        Wrapper<Menu> wrapper = Wrappers.<Menu>lambdaQuery()
                .in(Menu::getId, menuIds);
        Menu menu = new Menu();
        if (status == 1) {
            menu.setStatus(1);
        } else {
            menu.setStatus(0);
        }
        update(menu, wrapper);
    }

    @Transactional
    @Override
    public void removeMenuById(Long menuId) {
        if (menuId == null) {
            return;
        }
        Set<Long> menuIds = Sets.newHashSet(menuId);
        //TODO 处理子结点

        removeByIds(menuIds);
        roleMenuService.removeByMenuId(menuIds);
    }

    @Override
    public void updateMenu(MenuUpdatedParam param) {
        Menu updateBean = new Menu();
        BeanUtils.copyProperties(param, updateBean);
        System.out.println("updateBean");
        System.out.println(updateBean);
        updateById(updateBean);
    }

    @Override
    public void removeMenuByIdsOfBean(Collection<Menu> menus) {
        if (menus == null || menus.isEmpty()) {
            return;
        }
        Set<Long> removeMenuIds = menus.stream()
                .filter(menu -> menu != null)
                .map(menu -> {
                    return menu.getId();
                }).collect(Collectors.toSet());
        if (removeMenuIds.isEmpty()) {
            return;
        }
        removeByIds(removeMenuIds);
        roleMenuService.removeByMenuId(removeMenuIds);
    }

    @Transactional
    @Override
    public void addMenu(MenuAddParam param) {
        Menu add = new Menu();
        BeanUtils.copyProperties(param, add);

        if (add.getParentId() == null) add.setParentId(0L);
        if (add.getDescription() == null) add.setDescription("");
        if (add.getComponent() == null) add.setComponent("");
        if (add.getUrl() == null) add.setUrl("");
        if (add.getPermissions() == null) add.setPermissions("");
        if (add.getIcon() == null) add.setIcon("");

        add.setPluginMenu(0);
        save(add);
    }

    @Override
    public List<Menu> findMenusByRoleId(String roleId) {
        if (roleId.equals(authProp.getSuperAdminId())) {
            return menuMapper.findMenus();
        } else {
            return menuMapper.findMenusByRoleId(roleId);
        }
    }

    @Override
    public List<Menu> findByCurrentRole(MenuQueryParam param) {
        Set<String> roleIds = AuthUtils.getCurrentRoleIds();
        System.out.println("roleIds"+ roleIds);
        if (roleIds == null || roleIds.isEmpty()) {
            return Collections.emptyList();
        }
        Set<Menu> menus = new HashSet<>();
        Set<Menu> has_parent_menu_set = new HashSet<Menu>();
        for (String roleCode : roleIds) {
            List<Menu> menu_list = findMenusByRoleId(roleCode);
            // 筛选有父节点的menu以及统计所有结点menu
            for (Menu menu : menu_list) {
                Long parentId = menu.getParentId();
                if (parentId != 0L) {
                    has_parent_menu_set.add(menu);
                }
                menus.add(menu);
            }
        }
        // 处理有父节点的menu，让父节点记录它
        for (Menu menu : has_parent_menu_set) {
            Long parentId = menu.getParentId();
            for (Menu m : menus) {
                // 如果找到父节点就设置父节点的childrens
                if (m.getId() == parentId) {
                    List<Menu> childrens = m.getChildren();
                    if (childrens == null) {
                        childrens = new ArrayList<>();
                    }
                    childrens.add(menu);
                    m.setChildren(childrens);

                }
            }
        }
        // 过滤掉非父节点
        Iterator<Menu> iterator = menus.iterator();
        while (iterator.hasNext()) {
            Menu menu = iterator.next();
            if (menu.getParentId() != 0L) {
                iterator.remove();
            }
        }
        System.out.println(param);
        // 处理查询条件
        if (param != null) {
            if (param.getMenuName() != null && !StrUtil.isBlank(param.getMenuName())) {
                menus = menus.stream().filter(menu ->
                        param.getMenuName().equals(menu.getMenuName())).collect(Collectors.toSet());

            }
            if (param.getStatus() != null) {
                menus = menus.stream().filter(menu ->
                        param.getStatus() == menu.getStatus()).collect(Collectors.toSet());
            }
        }
        return menus.stream().toList();
    }

    //
    ///**
    // * 处理插件菜单
    // *
    // * @param navigationInfo 导航模型
    // * @param menu           当前菜单
    // * @param requestAddress 当前请求的地址
    // */
    //private NavigationVo.PluginWebInfo processPluginMenu(NavigationInfo navigationInfo, Menu menu, String requestAddress) {
    //    navigationInfo.setPath(HttpUtils.pathJoin(menu.getPluginRootRouting(), menu));
    //    navigationInfo.setComponent(PLUGIN_COMPONENT);
    //
    //    NavigationVo.PluginWebInfo pluginWebInfo = new NavigationVo.PluginWebInfo();
    //    pluginWebInfo.setAppName(menu.getPluginAppName());
    //    String pluginAppPath = menu.getPluginAppPath();
    //    if (!HttpUtils.isHttpUrl(pluginAppPath)) {
    //        pluginAppPath = requestAddress + HttpUtils.pathJoin(PluginConfig.STATIC_RESOURCE_PATH_PREFIX,
    //                pluginAppPath);
    //    }
    //    pluginWebInfo.setAppPath(pluginAppPath);
    //    pluginWebInfo.setRootRouting(menu.getPluginRootRouting());
    //    return pluginWebInfo;
    //}

    private static List<Menu> buildPermissionTree(List<Menu> menuList) {
        Map<Long, List<Menu>> parentIdToPermissionListMap = menuList.stream().peek(p -> {
            if (StringUtils.startsWith(p.getUrl(), "/")) {
                p.setUrl(SLASH_PATTERN.matcher(p.getUrl()).replaceFirst("#"));
            }
        }).collect(Collectors.groupingBy(Menu::getParentId));
        List<Menu> rootLevelPermissionList = parentIdToPermissionListMap.getOrDefault(0, Collections.emptyList());
        fetchChildren(rootLevelPermissionList, parentIdToPermissionListMap);
        return rootLevelPermissionList;
    }

    private static void fetchChildren(List<Menu> menuList, Map<Long, List<Menu>> parentIdToPermissionListMap) {
        if (CollectionUtils.isEmpty(menuList)) {
            return;
        }
        for (Menu menu : menuList) {
            List<Menu> childrenList = parentIdToPermissionListMap.get(menu.getId());
            fetchChildren(childrenList, parentIdToPermissionListMap);
            menu.setChildren(childrenList);
        }
    }
}
